package com.studynotes.dev.tech.common.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.studynotes.dev.tech.common.enums.DBTypeEnum;
import com.studynotes.dev.tech.common.enums.DriverClassNameEnum;
import com.studynotes.dev.tech.common.pool.DataSourceCachePool;
import com.studynotes.dev.tech.exception.GlobalException;
import com.studynotes.dev.tech.model.vo.dataSourceLinkConfig.DataSourceLinkConfigView;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Objects;

/**
 * @author Liu XiaoJun
 * @description: 操作数据源缓存池工具类（Spring JDBC 实时数据库访问）
 * @date 2025-11-07 15:33:01
 */
@Slf4j
public class DynamicDBUtil {

    /**
     * 通过 dbLinkKey ,获取数据源
     *
     * @param dbLinkKey Spring注入DS的ID
     * @return 数据源链接配置视图对象
     */
    public static DruidDataSource getDbSourceByDbLinkKey(final String dbLinkKey) {
        //先判断缓存中是否存在数据库链接
        DruidDataSource cacheDbSource = DataSourceCachePool.getCacheBasicDataSource(dbLinkKey);
        if (cacheDbSource != null && !cacheDbSource.isClosed()) {
            log.debug("--------getDbSourceByDbLinkKey------------------从缓存中获取DB连接-------------------");
            return cacheDbSource;
        } else {
            //获取多数据源配置
            DataSourceLinkConfigView dbSource = DataSourceCachePool.getCacheDynamicDataSourceModel(dbLinkKey);
            if(Objects.isNull(dbSource)){
                throw new GlobalException("Spring注入DS的ID不存在,请检查数据库！");
            }
            DruidDataSource dataSource = getJdbcDataSource(dbSource);
            if(dataSource.isEnable()){
                DataSourceCachePool.putCacheBasicDataSource(dbLinkKey, dataSource);
            }else{
                throw new GlobalException("动态数据源连接失败，dbLinkKey："+dbLinkKey);
            }
            log.info("--------getDbSourceByDbLinkKey ------------------创建DB数据库连接-------------------");
            return dataSource;
        }
    }

    /**
     * 获取数据源【最底层方法，不要随便调用】
     *
     * @param dbSource 数据源链接配置视图对象
     * @return 数据库源
     */
    private static DruidDataSource getJdbcDataSource(final DataSourceLinkConfigView dbSource) {
        DruidDataSource dataSource = new DruidDataSource();

        String driverClassName = DriverClassNameEnum.of(DBTypeEnum.of(dbSource.getDbType()).getCode()).getDriverClassName();
        String url = dbSource.getDbUrl();
        String dbUser = dbSource.getDbUser();
        String dbPassword = dbSource.getDbPass();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setTestWhileIdle(true);
        dataSource.setTestOnBorrow(false);
        dataSource.setTestOnReturn(false);
        dataSource.setBreakAfterAcquireFailure(true);
        dataSource.setConnectionErrorRetryAttempts(0);
        dataSource.setUsername(dbUser);
        dataSource.setMaxWait(60000);
        dataSource.setPassword(dbPassword);

        log.info("******************************************");
        log.info("*                                        *");
        log.info("*====【{}】=====Druid连接池已启用 ====*", dbSource.getDbLinkName());
        log.info("*                                        *");
        log.info("******************************************");
        return dataSource;
    }

    /**
     * 关闭数据库连接池
     *
     * @param dbLinkKey Spring注入DS的ID
     */
    public static void closeDbKey(final String dbLinkKey) {
        DruidDataSource dataSource = getDbSourceByDbLinkKey(dbLinkKey);
        try {
            if (!dataSource.isClosed()) {
                dataSource.getConnection().commit();
                dataSource.getConnection().close();
                dataSource.close();
            }
        } catch (SQLException e) {
            throw new GlobalException("");
        }
    }

    /**
     * 获取Jdbc模板
     * @param dbLinkKey Spring注入DS的ID
     * @return Jdbc模板
     */
    private static JdbcTemplate getJdbcTemplate(String dbLinkKey) {
        DruidDataSource dataSource = getDbSourceByDbLinkKey(dbLinkKey);
        return new JdbcTemplate(dataSource);
    }

    /**
     * 获取连接
     * @param url 数据库链接
     * @param username 用户名
     * @param password 密码
     * @param driverName 数据库驱动名称
     * @return 返回链接
     */
    public static Connection getConn(String url, String username, String password, String driverName) {
        Connection conn = null;
        try {
            Class.forName(driverName);
            conn = DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            throw new GlobalException("数据库无法连接,问题："+e.getMessage(), e);
        }

        return conn;
    }

    /**
     * 关闭数据库连接
     * @param conn 链接
     */
    public static void closeConnection(Connection conn) {
        try {
            if(conn!=null){
                conn.close();
            }
        } catch (SQLException e) {
            throw new GlobalException("关闭数据库链接失败：", e);
        }
    }

}
